// Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
// This source file is part of the Cangjie project, licensed under Apache-2.0
// with Runtime Library Exception.
//
// See https://cangjie-lang.cn/pages/LICENSE for license information.

#ifndef CANGJIE_MIGRATOR_UPDATE_INSTANCE
#define CANGJIE_MIGRATOR_UPDATE_INSTANCE

#include <map>
#include <string>
#include <vector>
#include <memory>

#include "cangjie/Frontend/CompilerInstance.h"
#include "cangjie/AST/Node.h"

#include "Actions/Action.h"
#include "Rules/ImportRule.h"
#include "Path.h"
#include "FileContent.h"
#include "FileImportInfo.h"
#include "PackageCompileInfo.h"

namespace CangjieMigrator::UpdateInstance {

using Cangjie::AST::ASTKind;

class File final {
public:
    explicit File(const Path &path);

    Path GetPath() const;

    void Add(Actions::Action action);
    void Add(Actions::Replace replace);
    void Add(Actions::Comment comment);

    void Add(const Cangjie::AST::PackageSpec &node, const PositionRange &range);
    void Add(const Cangjie::AST::ImportSpec &node, const PositionRange &range);
    void Add(const Rules::Rule *rule);

    void ChangeImport();
    [[nodiscard]] bool NeedImportStdx() const;

    bool Generate(const Path &target) const;

    std::string GetContentInRange(const PositionRange &range);

private:
    Path path;
    FileImportInfo importInfo;
    std::set<const Rules::ImportRule *> matchImportRules;

    std::unique_ptr<FileContent> content;

    std::vector<Actions::Replace> replaceList;
    std::vector<Actions::Replace> includedReplaceList;
    std::vector<Actions::Replace> deprecatedReplaceList;

    std::vector<Actions::Comment> commentList;
};

class Package {
public:
    explicit Package(Path path);
    explicit Package(const PackageCompileInfo &info);

    const Path &GetPath() const;
    const std::vector<Path> &GetImportPaths() const;

    void AddImportPath(Path importPath);

    File &GetFile(const std::string &fileName);

    void ChangeImport();
    [[nodiscard]] bool NeedImportStdx() const;

    bool Generate(const Path &target);

private:
    const Path path;
    std::vector<Path> importPaths{};

    std::map<std::string, std::unique_ptr<File>> files;
};

class Project {
public:
    explicit Project(Path path);

    void SetPackages(const std::vector<PackageCompileInfo> &infos);
    std::vector<std::unique_ptr<Package>> &GetPackages();
    [[nodiscard]] bool NeedImportStdx() const;

private:
    const Path path;
    std::vector<std::unique_ptr<Package>> packages;
};

} // namespace CangjieMigrator::UpdateInstance

#endif // CANGJIE_MIGRATOR_UPDATE_INSTANCE
